package cn.gok.testclass;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/**
 * @Author: chenfan
 * @Description:  借助Class对象   操作未知类的对象的属性
 */
public class Demo02 {


    public static void main(String[] args) throws Exception {
        //1、获取Class实例
        Class<?> aClass = Class.forName("cn.gok.entity.Person");

        /*
            2、通过Class实例 创建出相应类的对象
                   jdk1.8版本：   aClass.newInstance();
                   1.8版本以后的调用方式： aClass.getConstructor().newInstance();
         */
        Object obj = aClass.getConstructor().newInstance();
        System.out.println(obj); // cn.gok.entity.Person@49e4cb85



        /*
          3、获取  Class实例代表类的属性
                在反射机制中， 每个属性，都被存放到一个Filed对象中

                getFields() : 只能获取public的属性， 返回指定类所有属性，以Field[]返回
                getField(String methodName)  获取指定的public方法


                getDeclaredFields()  获取包括private在内的所有属性
                getDeclaredField(String methodName)   获取包括private在内的指定的属性

         */

        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
            System.out.println("============================================");
            
        }

        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName());
            System.out.println("============================================");
        }



        /*
            4、对获取到的属性 取值 或 赋值
                   get(Object obj)  获取指定对象的属性值，
                        obj ： 为具体的某个对象

                   set(Object obj, Object value)
                        obj:   为具体的某个对象 （为哪个对象赋值）
                        value: 设置的具体值
         */
        Field personName = aClass.getField("personName");
        System.out.println(personName.get(obj));
        personName.set(obj,"李四");
        System.out.println(personName.get(obj));


        /*
            5、打破私有属性封装

                注: 当我们获取的属性为私有属性时，不能直接调用相应的get、set方法，否则会抛出异常

         */
        Field age = aClass.getDeclaredField("age");

        //setAccessible(true) 表示打破当前属性的私有封装， 然我们可以直接对该属性 设置值、获取值
        age.setAccessible(true);

        age.set(obj,19);
        System.out.println(age.get(obj));


    }

}
